import 'package:flutter/material.dart';

/// 时间线model
class BaseTimeLineStep {
  final Widget title;

  final Widget subtitle;

  final Widget content;

  final Widget stepWidget;

  /// 当BaseTimeLineStep需要更小的时候设置这个
  final double size;

  const BaseTimeLineStep({
    this.subtitle,
    this.stepWidget,
    @required this.title,
    this.content,
    this.size,
  }) : assert(title != null);
}

/// 动态时间线

class BaseTimeLineStepper extends StatefulWidget {
  final double size;
  final double subWidth;

  final List<BaseTimeLineStep> steps;

  final double distance;

  final ScrollPhysics physics;

  final Color circleColor;
  final Color lineColor;

  /// 图标上下的线的长度，影响着标题(title)和内容(content)之间的距离
  final double lineHeight;

  const BaseTimeLineStepper({Key key, @required this.steps, this.distance = 8, this.size = 16, this.subWidth = 66, this.physics, this.circleColor, this.lineColor, this.lineHeight = 12.0})
      : assert(steps != null),
        super(key: key);

  @override
  _BaseTimeLineStepperState createState() => _BaseTimeLineStepperState();
}

class _BaseTimeLineStepperState extends State<BaseTimeLineStepper> with TickerProviderStateMixin {
  List<Key> _keys;

  Color get _lineColor => widget.lineColor ?? Colors.grey[300];

  Color get _circleColor => widget.circleColor ?? Colors.grey[400];

  @override
  Widget build(BuildContext context) {
    _keys = List<Key>.generate(widget.steps.length, (int i) => Key(i.toString()));

    return ListView(
      shrinkWrap: true,
      physics: widget.physics ?? NeverScrollableScrollPhysics(),
      children: <Widget>[
        for (int i = 0; i < widget.steps.length; i += 1)
          Column(
            key: _keys[i],
            children: <Widget>[
              _buildVerticalHeader(i),
              _buildVerticalBody(i),
            ],
          ),
      ],
    );
  }

  bool _isFirst(int index) {
    return index == 0;
  }

  bool _isLast(int index) {
    return widget.steps.length - 1 == index;
  }

  Widget _buildLine(bool visible) {
    return Container(width: visible ? 1.0 : 0.0, height: widget.lineHeight, color: _lineColor);
  }

  Widget _buildCircle(int index) {
    return ClipOval(
      child: Container(width: widget.size, height: widget.steps[index].size != null ? widget.steps[index].size : widget.size, decoration: BoxDecoration(color: _circleColor, shape: BoxShape.circle), alignment: Alignment.center, child: widget.steps[index].stepWidget),
    );
  }

  Widget _buildVerticalHeader(int index) {
    return Container(
      child: Row(
        children: <Widget>[
          Container(width: widget.subWidth, margin: EdgeInsets.only(right: widget.distance), child: widget.steps[index].subtitle),
          Column(children: <Widget>[_buildLine(!_isFirst(index)), _buildCircle(index), _buildLine(!_isLast(index))]),
          Expanded(child: Container(margin: EdgeInsets.only(left: widget.distance), child: widget.steps[index].title)),
        ],
      ),
    );
  }

  Widget _buildVerticalBody(int index) {
    return IntrinsicHeight(
      child: Row(
        children: <Widget>[
          Container(width: widget.subWidth, margin: EdgeInsets.only(right: widget.distance)),
          SizedBox(width: widget.size, child: Center(child: Container(width: _isLast(index) ? 0.0 : 1.0, color: _lineColor))),
          Expanded(child: Container(margin: EdgeInsets.only(left: (widget.size / 2), bottom: 12), child: widget.steps[index].content)),
        ],
      ),
    );
  }
}
